Java Servlet
1. 개요
1. 개요
자바 서블릿은 자바 플랫폼의 API로서, 웹 서버에서 동적인 웹 페이지를 생성하기 위해 사용된다. 썬 마이크로시스템즈에 의해 개발되어 1997년에 최초로 등장했으며, 주로 웹 서버의 기능을 확장하고 HTTP 요청을 처리하여 응답을 생성하는 데 쓰인다.
이는 웹 개발 분야에서 서버 측 자바 애플리케이션의 핵심 구성 요소로 자리 잡았다. 서블릿은 JSP와 밀접한 관계를 가지며, 함께 사용되어 효율적인 동적 웹 콘텐츠 생성을 가능하게 한다.
2. 역사와 배경
2. 역사와 배경
자바 서블릿은 1997년 썬 마이크로시스템즈에 의해 처음 소개된 자바 플랫폼의 API이다. 당시 웹 서버는 정적인 HTML 페이지만을 제공하는 데 한계가 있었으며, 동적인 웹 콘텐츠를 생성할 수 있는 기술에 대한 필요성이 대두되고 있었다. 서블릿은 이러한 요구에 부응하여, 자바 언어의 이식성과 강력함을 바탕으로 웹 서버의 기능을 확장하고 동적인 웹 페이지를 생성하는 표준 방식을 제공하기 위해 개발되었다.
서블릿 기술의 등장 이전에는 CGI가 동적 웹 콘텐츠를 생성하는 주요 방법이었다. 그러나 CGI는 각 요청마다 새로운 프로세스를 생성해야 해서 서버 자원을 많이 소모하고 응답 속도가 느리다는 단점이 있었다. 서블릿은 이러한 문제를 해결하기 위해 설계되었으며, 자바 가상 머신 위에서 실행되어 요청을 처리함으로써 더 효율적인 성능을 제공한다. 서블릿은 HTTP 요청을 처리하고 응답을 생성하는 데 특화되어 있으며, 웹 애플리케이션의 핵심 로직을 담당하는 컴포넌트로 자리 잡았다.
이 기술은 이후 JSP의 기반이 되었으며, 두 기술은 함께 사용되어 자바 기반 웹 개발의 표준 아키텍처를 형성하는 데 기여했다. 서블릿의 등장은 자바가 엔터프라이즈급 웹 애플리케이션 개발의 주요 플랫폼으로 성장하는 데 중요한 발판을 마련했다.
3. 동작 원리와 생명주기
3. 동작 원리와 생명주기
3.1. 서블릿 컨테이너
3.1. 서블릿 컨테이너
서블릿 컨테이너는 자바 서블릿의 생명주기를 관리하고 실행 환경을 제공하는 웹 서버의 구성 요소이다. 이 컨테이너는 클라이언트로부터 들어오는 HTTP 요청을 받아 해당하는 서블릿을 찾아 실행하고, 서블릿이 생성한 응답을 다시 클라이언트에게 전송하는 역할을 한다. 서블릿 컨테이너는 웹 애플리케이션 서버의 핵심 모듈로 동작하며, 톰캣, 제티, 언더토우 등이 대표적인 구현체이다.
서블릿 컨테이너의 주요 기능은 서블릿 인스턴스의 생성과 소멸을 관리하는 것이다. 컨테이너는 서블릿의 init() 메서드를 호출하여 초기화하고, 요청이 들어올 때마다 service() 메서드를 통해 비즈니스 로직을 실행하며, 애플리케이션이 종료되거나 서블릿이 필요 없어지면 destroy() 메서드를 호출하여 자원을 정리한다. 이 과정을 통해 개발자는 복잡한 네트워크 통신이나 스레드 관리에 신경 쓰지 않고 순수한 요청 처리 로직에만 집중할 수 있다.
또한 서블릿 컨테이너는 웹 애플리케이션의 배포와 관리를 단순화한다. 개발자는 서블릿 클래스와 설정 파일을 WAR 파일 형태로 패키징하여 컨테이너에 배포하기만 하면 된다. 컨테이너는 배포된 애플리케이션의 설정을 읽고, 필요한 서블릿 매핑을 구성하며, 세션 관리와 같은 공통 서비스를 제공한다. 이는 서블릿 기반 웹 개발의 생산성을 크게 향상시킨 요소이다.
서블릿 컨테이너의 존재는 자바 기반 웹 기술의 발전에 기반이 되었다. 컨테이너가 제공하는 표준화된 실행 환경 위에서 JSP나 다양한 자바 웹 프레임워크들이 동작할 수 있게 되었으며, 이는 엔터프라이즈 애플리케이션 개발의 표준 아키텍처로 자리 잡는 데 결정적인 역할을 했다.
3.2. init(), service(), destroy()
3.2. init(), service(), destroy()
서블릿의 생명주기는 서블릿 컨테이너에 의해 관리되며, 주요 단계는 init(), service(), destroy() 메서드의 호출로 이루어진다. 이 세 가지 메서드는 자바의 javax.servlet.Servlet 인터페이스에 정의되어 있으며, 개발자는 주로 이를 상속받은 HttpServlet 클래스를 확장하여 웹 애플리케이션을 개발한다.
init() 메서드는 서블릿 인스턴스가 생성된 후 최초로 한 번만 호출된다. 이 단계에서 서블릿은 필요한 초기화 작업을 수행하며, 서블릿 컨테이너는 ServletConfig 객체를 매개변수로 전달하여 서블릿의 초기화 매개변수나 ServletContext에 대한 접근을 제공한다. 서블릿은 이 메서드가 성공적으로 완료되어야 클라이언트의 요청을 처리할 준비가 된 상태가 된다.
클라이언트로부터 HTTP 요청이 들어오면 컨테이너는 service() 메서드를 호출한다. 이 메서드는 요청의 종류(GET/POST 등)를 분석하여 doGet(), doPost() 등 해당하는 메서드로 처리를 위임한다. 따라서 개발자는 주로 service() 메서드를 직접 오버라이드하기보다는 doGet()이나 doPost() 같은 메서드를 구현하여 구체적인 요청 처리와 동적 웹 콘텐츠 생성을 담당하게 된다.
서블릿이 더 이상 필요하지 않을 때, 예를 들어 웹 애플리케이션이 중단되거나 컨테이너가 종료될 때 destroy() 메서드가 호출된다. 이는 서블릿 생명주기의 마지막 단계로, 데이터베이스 연결 종료나 자원 해제 같은 정리 작업을 수행하기 위한 기회를 제공한다. 이 메서드가 호출된 후에는 해당 서블릿 인스턴스는 가비지 컬렉션의 대상이 된다.
4. 주요 클래스와 인터페이스
4. 주요 클래스와 인터페이스
4.1. HttpServlet
4.1. HttpServlet
HttpServlet은 자바 서블릿 API의 핵심 클래스로, HTTP 프로토콜을 사용하는 웹 요청을 처리하기 위해 설계되었다. 이 클래스는 일반적인 서블릿 인터페이스를 구현한 추상 클래스로서, 개발자가 웹 서버에서 동적인 웹 페이지를 생성하는 로직에 집중할 수 있도록 HTTP 관련 기본 기능을 제공한다. 주로 웹 애플리케이션의 컨트롤러 역할을 담당하며, 클라이언트의 요청을 받아 비즈니스 로직을 수행하고 HTML이나 JSON 등의 형태로 응답을 생성한다.
HttpServlet 클래스는 service(), doGet(), doPost()와 같은 메서드를 정의한다. service() 메서드는 들어오는 HTTP 요청의 메서드(GET, POST, PUT, DELETE 등)를 자동으로 판별하여 해당하는 doXXX() 메서드로 라우팅한다. 따라서 개발자는 특정 HTTP 메서드를 처리하고자 할 때, doGet()이나 doPost()와 같은 메서드를 오버라이드(재정의)하기만 하면 된다. 이를 통해 HTTP 프로토콜의 세부 사항을 직접 처리할 필요 없이 핵심 로직에만 집중할 수 있다.
HttpServlet을 사용하려면 개발자는 이 클래스를 상속받는 새로운 서블릿 클래스를 작성해야 한다. 작성된 서블릿 클래스는 서블릿 컨테이너(예: 톰캣, 제티)에 의해 관리되며, web.xml 설정 파일이나 @WebServlet 같은 어노테이션을 통해 특정 URL 패턴에 매핑된다. 클라이언트가 매핑된 URL로 요청을 보내면, 서블릿 컨테이너는 해당 HttpServlet 객체의 생명주기를 관리하며 적절한 메서드를 호출하여 요청을 처리한다.
HttpServlet은 HttpServletRequest와 HttpServletResponse 객체를 매개변수로 받아 작업을 수행한다. HttpServletRequest 객체는 클라이언트가 보낸 요청 파라미터, 헤더, 쿠키 등의 정보를 담고 있으며, HttpServletResponse 객체는 응답 상태 코드, 콘텐츠 타입 설정, 그리고 최종 출력 내용을 작성하는 데 사용된다. 이를 통해 서블릿은 동적인 콘텐츠 생성은 물론, 리다이렉트나 세션 관리와 같은 고급 웹 기능도 구현할 수 있다.
4.2. HttpServletRequest와 HttpServletResponse
4.2. HttpServletRequest와 HttpServletResponse
HttpServletRequest와 HttpServletResponse는 자바 서블릿 API의 핵심 인터페이스로, 클라이언트의 HTTP 요청 정보를 담고 이에 대한 응답을 생성하는 역할을 한다. 서블릿 컨테이너는 웹 서버로부터 전달받은 요청을 바탕으로 HttpServletRequest 객체를 생성하고, 서블릿이 작성할 응답을 위한 HttpServletResponse 객체를 함께 제공한다. 서블릿 개발자는 이 두 객체를 통해 HTTP 프로토콜의 세부 사항을 직접 다루지 않고도 웹 요청을 처리하고 동적인 콘텐츠를 생성할 수 있다.
HttpServletRequest 객체는 클라이언트로부터 전송된 모든 요청 정보를 캡슐화한다. 여기에는 HTTP 메서드 (GET, POST 등), 요청 URL, 헤더 정보, 쿼리 문자열(Query String)과 같은 요청 매개변수, 그리고 클라이언트 IP 주소 등이 포함된다. 또한, 쿠키와 세션과 같은 클라이언트 상태 정보를 관리하는 메서드도 제공하여, 사용자별 데이터를 유지하는 데 활용된다.
반면, HttpServletResponse 객체는 서버에서 클라이언트로 보낼 응답을 구성하는 데 사용된다. 개발자는 이 객체를 이용해 HTTP 상태 코드 (예: 200 OK, 404 Not Found)를 설정하고, 응답에 포함될 콘텐츠 타입(Content-Type)을 지정하며, 새로운 헤더나 쿠키를 추가할 수 있다. 가장 중요한 기능은 getWriter() 메서드나 getOutputStream() 메서드를 통해 얻은 출력 스트림에 HTML이나 기타 데이터를 직접 작성하여 동적인 웹 페이지를 생성하는 것이다.
이 두 인터페이스는 서블릿이 웹 애플리케이션의 비즈니스 로직에 집중할 수 있도록 하면서도, 필요시 낮은 수준의 HTTP 정보에도 접근할 수 있는 유연성을 제공한다. 이를 통해 자바 기반의 웹 서버 확장 및 동적 웹 콘텐츠 생성을 효율적으로 구현할 수 있다.
4.3. ServletContext와 ServletConfig
4.3. ServletContext와 ServletConfig
서블릿 컨테이너는 웹 애플리케이션을 실행할 때 ServletContext와 ServletConfig라는 두 가지 중요한 객체를 생성하여 서블릿에 제공한다. 이 두 객체는 서블릿이 실행 환경과 설정 정보에 접근할 수 있게 해주는 인터페이스 역할을 한다. 둘 다 설정 정보를 담고 있다는 점에서 유사하지만, 그 범위와 목적에 있어서 명확한 차이가 존재한다.
ServletConfig는 개별 서블릿의 초기화 파라미터를 담는 객체이다. 서블릿이 초기화될 때 서블릿 컨테이너에 의해 생성되며, 특정 서블릿 인스턴스에 종속된다. 이는 web.xml 파일의 <servlet> 태그 내 <init-param>으로 정의하거나, @WebServlet 어노테이션의 initParams 속성으로 정의할 수 있는 정보를 가리킨다. 따라서 서블릿 A와 서블릿 B는 서로 다른 ServletConfig 객체를 가지며, 각자에게 할당된 고유의 설정값만을 읽을 수 있다. 주로 데이터베이스 연결 정보나 파일 경로처럼 해당 서블릿만 사용하는 구체적인 값을 저장하는 데 활용된다.
반면 ServletContext는 웹 애플리케이션 전체에 공유되는 정보와 자원을 관리하는 객체이다. 서블릿 컨테이너가 웹 애플리케이션(WAR 파일)을 시작할 때 하나만 생성되며, 해당 애플리케이션에 속한 모든 서블릿과 JSP가 동일한 객체를 참조한다. 애플리케이션 전역 초기화 파라미터는 web.xml의 <context-param>으로 설정할 수 있다. 또한 ServletContext는 애플리케이션 범위의 속성을 저장하고 공유할 수 있는 공간을 제공하며, 서블릿 간의 리다이렉트와 디스패치를 위한 메서드, 그리고 서버 상의 실제 파일 경로를 얻는 기능 등을 포함한다. 이는 전체 애플리케이션이 공통으로 사용해야 하는 설정이나 자원을 관리하는 데 적합하다.
요약하면, ServletConfig는 특정 서블릿을 위한 '개인 설정'을, ServletContext는 웹 애플리케이션 전체를 위한 '공용 설정 및 자원'을 담당한다고 볼 수 있다. 서블릿은 init(ServletConfig config) 메서드를 통해 자신의 ServletConfig 객체를 전달받으며, 이를 통해 ServletContext 객체에도 접근할 수 있다. 이 두 인터페이스를 통해 서블릿은 유연하게 구성 정보를 관리하고 자원을 공유하며 효율적으로 동작할 수 있다.
5. 요청 처리와 응답 생성
5. 요청 처리와 응답 생성
5.1. GET/POST 요청 처리
5.1. GET/POST 요청 처리
GET과 POST는 HTTP 요청 메서드 중 가장 널리 사용되는 방식이다. 자바 서블릿은 HttpServlet 클래스를 상속받아 이들 요청을 처리하는 메서드를 오버라이드함으로써 각각의 요청에 맞는 로직을 구현한다. 서블릿 컨테이너는 클라이언트로부터 들어온 요청의 메서드 종류를 판단하여, 서블릿 내의 해당 doGet() 또는 doPost() 메서드를 자동으로 호출한다. 이 메서드들은 HttpServletRequest 객체와 HttpServletResponse 객체를 매개변수로 받아, 요청 정보를 분석하고 적절한 동적 응답을 생성하는 역할을 한다.
doGet() 메서드는 주로 정보를 조회하거나 검색하는 요청을 처리한다. 이 메서드로 전달되는 데이터는 URL의 쿼리 문자열에 포함되기 때문에 길이 제한이 있고 보안에 취약하다는 특징이 있다. 반면, doPost() 메서드는 서버에 데이터를 제출하거나 업데이트하는 요청을 처리한다. 요청 본문을 통해 데이터를 전송하므로 대용량 데이터 전송에 적합하며, 데이터가 직접 URL에 노출되지 않아 상대적으로 안전하다. 서블릿 개발자는 각 메서드의 용도에 맞게 비즈니스 로직을 설계해야 한다.
실제 구현에서는 doGet() 메서드 내에서 HTML 폼을 출력하고, 사용자가 폼을 작성하여 제출하면 doPost() 메서드가 그 데이터를 처리하는 패턴이 자주 사용된다. 또한, 하나의 서블릿이 여러 종류의 요청을 처리할 수 있도록, doGet() 메서드 내부에서 doPost()를 호출하거나 그 반대의 방식을 사용하여 코드 중복을 줄이는 방법도 있다. 요청 처리의 마지막 단계에서는 HttpServletResponse 객체의 메서드를 이용해 HTML, JSON, 또는 일반 텍스트 등의 형태로 클라이언트에게 최종 응답을 출력하게 된다.
5.2. 리다이렉트와 디스패치
5.2. 리다이렉트와 디스패치
서블릿은 클라이언트의 요청을 처리한 후, 다른 자원으로의 흐름을 제어하거나 응답을 다른 자원에게 위임하는 기능을 제공한다. 대표적인 방법으로는 리다이렉트와 디스패치가 있다. 이 두 방식은 모두 클라이언트의 요청을 다른 자원으로 전달하지만, 그 동작 방식과 사용 목적에서 근본적인 차이를 보인다.
리다이렉트는 HttpServletResponse 객체의 sendRedirect() 메서드를 사용하여 구현한다. 이 방식은 서버가 클라이언트에게 특정 URL로 새로운 요청을 보내도록 지시하는 HTTP 응답을 전송한다. 결과적으로 클라이언트의 브라우저 주소창의 URL이 변경되며, 이는 완전히 새로운 요청이므로 기존의 HttpServletRequest와 HttpServletResponse 객체가 새로 생성된다. 따라서 리다이렉트는 다른 도메인이나 외부 사이트로 이동할 때, 또는 요청 데이터를 공유할 필요가 없는 단순한 페이지 전환에 주로 사용된다.
반면에 디스패치는 서버 내부에서 요청 처리를 다른 자원으로 포워딩하는 방식이다. RequestDispatcher 인터페이스의 forward() 메서드가 대표적이다. 이 방법은 클라이언트에게 알리지 않고 서버 내부에서만 요청과 응답 객체를 그대로 전달하여 다음 자원이 처리를 이어간다. 클라이언트의 브라우저 주소창은 최초 요청한 URL을 유지한 채로 서버 내의 다른 서블릿이나 JSP가 생성한 최종 결과를 받게 된다. 이를 통해 요청 정보와 데이터를 유지한 채로 로직을 분리하거나 뷰를 생성하는 작업을 위임할 수 있다.
요약하면, 리다이렉트는 클라이언트를 통해 이루어지는 두 번의 요청이며 URL이 변경되고, 디스패치는 서버 내부에서 이루어지는 한 번의 요청 처리로 URL이 변하지 않는다. 애플리케이션의 설계에 따라 요청과 응답 객체의 생명주기와 데이터 공유 필요성에 맞게 적절한 방식을 선택하여 사용한다.
5.3. 쿠키와 세션 관리
5.3. 쿠키와 세션 관리
쿠키와 세션은 HTTP의 무상태(Stateless) 특성을 보완하여 웹 애플리케이션에서 사용자 상태를 유지하기 위한 핵심 메커니즘이다. 자바 서블릿 API는 이 두 가지 기술을 효과적으로 다룰 수 있는 클래스와 인터페이스를 제공한다.
쿠키는 서버가 사용자의 웹 브라우저에 저장하는 작은 텍스트 정보이다. 서블릿에서는 javax.servlet.http.Cookie 클래스를 사용하여 쿠키를 생성하고, HttpServletResponse 객체의 addCookie() 메서드로 클라이언트에 전송한다. 이후 클라이언트로부터의 요청에는 HttpServletRequest 객체의 getCookies() 메서드를 통해 쿠키 정보가 자동으로 포함되어 서버로 전달된다. 쿠키는 도메인, 경로, 만료 시간 등을 설정할 수 있으며, 주로 사용자 로그인 유지, 언어 설정, 장바구니 정보 저장 등에 활용된다.
반면, 세션은 서버 측에 사용자별 상태 정보를 저장하는 방식이다. 서블릿 컨테이너는 클라이언트가 최초로 요청을 보낼 때 고유한 세션 ID를 생성하고, 이 ID는 주로 쿠키나 URL 재작성을 통해 클라이언트와 교환된다. 서블릿에서는 HttpServletRequest의 getSession() 메서드를 호출하여 현재 요청과 연관된 HttpSession 객체를 얻을 수 있다. 이 객체에 setAttribute(), getAttribute() 메서드를 사용해 필요한 데이터를 저장하고 조회한다. 세션은 서버의 메모리나 데이터베이스에 저장되며, 보안이 중요한 사용자 인증 정보나 임시 데이터를 다루는 데 적합하다.
쿠키와 세션은 각각의 장단점에 따라 선택적으로 또는 함께 사용된다. 쿠키는 클라이언트에 저장되어 서버 자원을 소모하지 않지만, 보안에 취약하고 저장 용량에 제한이 있다. 세션은 보안성이 상대적으로 높고 많은 데이터를 저장할 수 있으나, 서버의 메모리 부하를 초래할 수 있다. 따라서 로그인 세션은 서버 측에서 관리하고, 단순한 환경 설정은 클라이언트 측 쿠키에 저장하는 등 혼용하여 설계하는 것이 일반적이다.
6. 배포와 설정
6. 배포와 설정
6.1. web.xml과 어노테이션
6.1. web.xml과 어노테이션
서블릿 애플리케이션의 구성과 설정을 정의하는 방법은 크래 두 가지로 나뉜다. 전통적인 방법은 web.xml이라는 배포 서술자 파일을 사용하는 것이며, 현대적인 방법은 자바 어노테이션을 활용하는 것이다.
web.xml 파일은 WAR 파일 내 WEB-INF 디렉토리에 위치하며, XML 형식으로 작성된다. 이 파일은 서블릿, 필터, 리스너의 선언과 매핑, 초기화 파라미터, 세션 설정, MIME 타입 매핑 등 애플리케이션의 전체적인 구성을 중앙에서 관리한다. 예를 들어, 특정 URL 패턴으로 들어오는 요청을 어떤 서블릿 클래스가 처리할지 명시적으로 정의할 수 있다. 이 방식의 장점은 설정이 코드와 분리되어 있어 애플리케이션의 동작을 코드 재컴파일 없이 변경할 수 있으며, 모든 설정을 한눈에 확인하기 쉽다.
반면, 서블릿 3.0 사양부터 도입된 어노테이션 기반 설정은 코드 내에서 직접 구성을 정의하는 방식을 제공한다. @WebServlet, @WebFilter, @WebListener 등의 어노테이션을 각각의 클래스에 부여함으로써 web.xml에 일일이 등록하지 않고도 서블릿 컨테이너가 해당 컴포넌트를 인식하고 등록할 수 있다. 이 방식은 설정이 관련 코드 바로 옆에 위치하여 유지보수성을 높이고, 배포 서술자 파일의 복잡성을 줄여준다.
두 방식은 상호 배타적이지 않으며 함께 사용될 수 있다. 서블릿 컨테이너는 어노테이션을 먼저 스캔한 후 web.xml의 설정을 적용하는데, 충돌이 발생할 경우 일반적으로 web.xml의 설정이 우선권을 가진다. 개발자는 프로젝트의 규모, 유지보수 정책, 프레임워크 요구사항에 따라 적절한 설정 방식을 선택하거나 혼용한다.
6.2. WAR 파일
6.2. WAR 파일
WAR 파일은 웹 애플리케이션을 배포하기 위한 표준 자바 아카이브 형식이다. WAR는 Web Application Archive의 약자로, JSP 파일, 자바 클래스, 라이브러리, HTML, 이미지 파일, 그리고 웹 애플리케이션의 설정 정보를 담은 web.xml 파일 등 하나의 웹 애플리케이션을 구성하는 모든 자원을 하나의 파일로 묶어 패키징한다.
이 파일은 서블릿 컨테이너나 웹 애플리케이션 서버에 배포되어 실행된다. 톰캣, 제이보스, 웹로직과 같은 서버는 WAR 파일을 받아 특정 디렉터리 구조로 압축을 풀고, 내부의 web.xml 설정을 읽어 서블릿과 필터, 리스너를 초기화하여 애플리케이션을 가동시킨다. 이는 애플리케이션의 개발, 테스트, 배포 과정을 표준화하고 단순화하는 데 기여한다.
WAR 파일의 내부 구조는 JAR 파일과 유사하지만, 정해진 웹 애플리케이션 디렉터리 구조를 따른다. 예를 들어, 컴파일된 자바 클래스 파일은 /WEB-INF/classes/ 디렉터리에, 외부 라이브러리 JAR 파일은 /WEB-INF/lib/ 디렉터리에 위치해야 한다. 이 표준화된 구조 덕분에 서로 다른 서블릿 컨테이너 간에도 호환성을 유지하며 배포가 가능하다.
개발자는 이클립스, 인텔리J, 메이븐, 그레이들과 같은 개발 도구나 빌드 도구를 사용하여 프로젝트를 WAR 파일로 쉽게 패키징할 수 있다. 최신 자바 EE 및 자카르타 EE 스펙에서는 web.xml 대신 어노테이션을 통한 설정을 권장하지만, WAR 파일 자체는 여전히 표준 배포 단위로서의 역할을 유지하고 있다.
7. 필터와 리스너
7. 필터와 리스너
서블릿 필터는 클라이언트의 요청이 서블릿에 도달하기 전이나 서블릿의 응답이 클라이언트에게 반환되기 전에 특정 작업을 수행하는 객체이다. 주로 인코딩 변환, 인증 및 권한 부여, 로깅, 데이터 압축과 같은 공통적인 전처리 또는 후처리 작업을 구현하는 데 사용된다. 필터는 javax.servlet.Filter 인터페이스를 구현하며, web.xml 파일에 설정하거나 @WebFilter 어노테이션을 통해 배포 서술자에 등록하여 사용한다. 여러 개의 필터가 체인으로 연결되어 순차적으로 실행될 수 있어, 요청과 응답에 대한 일관된 처리 파이프라인을 구성할 수 있다.
서블릿 리스너는 웹 애플리케이션의 생명주기 내에서 발생하는 특정 이벤트를 감지하고 그에 따른 작업을 수행하는 객체이다. 리스너는 크게 ServletContext에 관련된 이벤트, HttpSession에 관련된 이벤트, ServletRequest에 관련된 이벤트를 처리하는 세 가지 범주로 나눌 수 있다. 예를 들어, 애플리케이션이 시작되거나 종료될 때, 사용자 세션이 생성되거나 소멸될 때, 요청 객체의 속성이 추가되거나 제거될 때와 같은 시점에 코드를 실행할 수 있다. 리스너는 해당 이벤트 인터페이스를 구현하고 마찬가지로 web.xml 또는 @WebListener 어노테이션을 통해 등록하여 사용한다.
필터와 리스너는 서블릿 API의 중요한 확장 메커니즘으로, 핵심 비즈니스 로직을 담당하는 서블릿 코드와는 분리된 형태로 교차 관심사를 모듈화하고 관리할 수 있게 해준다. 이를 통해 애플리케이션의 유지보수성과 재사용성을 높일 수 있으며, 보안, 감사, 국제화와 같은 애플리케이션 전반에 걸쳐 적용해야 하는 기능을 효율적으로 구현하는 데 기여한다.
8. JSP와의 관계
8. JSP와의 관계
JSP는 자바 서블릿 기술의 확장으로, 서블릿만으로 HTML을 생성하는 것이 번거로웠던 점을 보완하기 위해 등장했다. JSP는 HTML 문서 내에 자바 코드를 삽입할 수 있는 스크립트 요소를 제공하여, 웹 페이지의 동적 콘텐츠를 보다 쉽게 작성할 수 있게 해준다. 웹 애플리케이션 서버는 JSP 파일을 요청받으면, 이를 자동으로 서블릿 소스 코드로 변환(변역)하고 컴파일하여 실행한다. 따라서 JSP는 결국 서블릿으로 실행되는 구조이다.
이러한 관계는 MVC 패턴을 구현하는 데 적합한 역할 분담을 가능하게 했다. 서블릿은 주로 컨트롤러 역할을 담당하여 사용자의 요청을 처리하고, 비즈니스 로직을 수행하며, 적절한 JSP 파일로 포워딩하는 흐름을 제어한다. 반면 JSP는 뷰 역할에 집중하여, 서블릿이나 자바빈즈를 통해 전달받은 데이터를 바탕으로 최종적인 HTML 응답을 생성하는 데 특화되어 있다.
초기에는 JSP 내에 상당량의 자바 코드가 포함되는 경우가 많았으나, 이는 유지보수를 어렵게 만들었다. 이를 개선하기 위해 등장한 JSTL과 EL은 JSP 페이지에서 자바 코드의 사용을 최소화하고, 태그 기반의 선언적 방식으로 로직을 처리할 수 있도록 도와주었다. 결과적으로 현대적인 자바 웹 애플리케이션에서는 서블릿이 애플리케이션의 흐름을 제어하고, JSP는 표현 계층을 담당하는 명확한 분업 구조가 정립되었다.
9. 장단점
9. 장단점
서블릿의 가장 큰 장점은 플랫폼 독립성이다. 자바 언어로 작성되기 때문에, 서블릿 코드는 윈도우, 리눅스, 유닉스 등 다양한 운영 체제에서 자바 가상 머신이 설치된 웹 서버라면 수정 없이 실행될 수 있다. 이는 개발과 배포의 유연성을 크게 높인다. 또한 서블릿은 멀티스레딩을 효율적으로 지원하여, 단일 인스턴스가 여러 클라이언트의 요청을 동시에 처리할 수 있어 자원 관리와 성능 면에서 유리하다. 서버 측에서 실행되기 때문에 클라이언트의 환경에 구애받지 않고 강력한 비즈니스 로직을 구현할 수 있으며, 자바의 방대한 표준 라이브러리와 객체 지향 프로그래밍의 장점을 그대로 활용할 수 있다.
반면, 서블릿의 단점은 주로 프레젠테이션 계층의 구현 복잡성에서 비롯된다. HTML 코드를 생성하기 위해 자바 코드 내에 문자열을 직접 삽입하는 방식은 코드의 가독성을 떨어뜨리고 유지보수를 어렵게 만든다. 이 문제를 해결하기 위해 JSP가 등장하게 되었다. 또한, 서블릿의 생명주기와 설정은 초기 학습 곡선을 높이는 요인이 될 수 있다. 웹 애플리케이션의 규모가 커질수록 web.xml 설정 파일이 복잡해지거나, 서블릿 클래스의 수가 많아져 관리가 번거로워질 수 있다는 점도 지적된다.
전반적으로 서블릿은 자바 EE 웹 애플리케이션의 핵심 기술로서, 견고한 서버 측 컴포넌트를 만드는 데 탁월한 기반을 제공한다. MVC 패턴에서 컨트롤러의 역할을 수행하는 데 적합하며, 현대의 많은 자바 웹 프레임워크들이 내부적으로 서블릿 기술을 기반으로 구축되어 있다. 따라서 서블릿에 대한 이해는 스프링 프레임워크와 같은 고수준 프레임워크를 효과적으로 사용하는 데 필수적인 기초 지식이 된다.
